package Utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Clase que gestiona las descargas de las URLS.
 * 
 * @author Alejandro Gudiña Gil
 * @author Jordi Parrón Granados
 * @author Victor Tello Ruiz
 */
public class GestionUrls {

	public ArrayList<String> arrayFiles;
	public static final String EXT_ZIP = ".zip";
	public static final String EXT_GZIP = ".gz";
	public static final String EXT_ASC = ".asc";
	static final String PATH = "C:/Users/2111647/";

	/**
	 * Funci�n para guardar el contenido de una URL. Para ello se redirecciona
	 * al FileOutputStream.
	 * 
	 * @param is
	 *            InputStream a guardar
	 * @param url
	 *            Url que guardaremos
	 * @throws IOException
	 *             Excepci�n de Entrada y salida.
	 */
	public void saveUrlContent(InputStream is, URL url) throws IOException {
		try {
			FileOutputStream fos = new FileOutputStream(PATH
					+ getNameFileByUrl(url,""));

			// buffer para ir leyendo.
			byte[] array = new byte[1];

			// Primera lectura y bucle hasta el final
			int leido = is.read(array);
			while (leido > 0) {
				fos.write(array, 0, leido);
				leido = is.read(array);
			}
			// Cierre de conexion y fichero.
			is.close();
			fos.close();
			System.out.println("Archivo Guardado en: " + PATH);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Funci�n para guardar el contenido de una URL en un ZIP. Para ello se
	 * redirecciona la salida del OutputStream del ZIP al FileOutputStream.
	 * 
	 * @param is
	 *            InputStream a guardar
	 * @param url
	 *            Url que guardaremos
	 * @throws IOException
	 *             Excepci�n de Entrada y salida.
	 */
	public void saveUrlContentOnZip(InputStream is, URL url) throws IOException {
		try {
			ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(PATH
					+ getNameFileByUrl(url, EXT_ZIP)));
			zos.putNextEntry(new ZipEntry(getNameFileByUrl(url, "")));
			// buffer para ir leyendo.
			byte[] array = new byte[1];

			// Primera lectura y bucle hasta el final
			int leido = is.read(array);
			while (leido > 0) {
				zos.write(array, 0, leido);
				leido = is.read(array);
			}
			// Cierre de conexion y fichero.
			is.close();
			zos.finish();
			zos.close();
			System.out.println("Archivo Guardado en: " + PATH);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Funci�n para guardar el contenido de una URL en un ZIP.GZ. Para ello se
	 * redirecciona la salida del OutputStream del GZIP al FileOutputStream.
	 * 
	 * @param is
	 *            InputStream a guardar
	 * @param url
	 *            Url que guardaremos
	 * @throws IOException
	 *             Excepci�n de Entrada y salida.
	 */
	public void saveUrlContentOnGZip(InputStream is, URL url)
			throws IOException {
		try {
			GZIPOutputStream gos = new GZIPOutputStream(new FileOutputStream(
					PATH + getNameFileByUrl(url, EXT_GZIP)));

			// buffer para ir leyendo.
			byte[] array = new byte[1];

			// Primera lectura y bucle hasta el final
			int leido = is.read(array);
			while (leido > 0) {
				gos.write(array, 0, leido);
				leido = is.read(array);
			}
			// Cierre de conexion y fichero.
			is.close();
			gos.finish();
			gos.close();
			System.out.println("Archivo Guardado en: " + PATH);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Funci�n para guardar el contenido de una URL en un ZIP.GZ. Para ello se
	 * redirecciona la salida del OutputStream del ZIP al OutputStream del GZIP
	 * y este al FileOutputStream.
	 * 
	 * @param is
	 *            InputStream a guardar
	 * @param url
	 *            Url que guardaremos
	 * @throws IOException
	 *             Excepci�n de Entrada y salida.
	 */
	public void saveUrlContentOnZipAndGzip(InputStream is, URL url)
			throws IOException {
		try {
			String nameFile = getNameFileByUrl(url, EXT_ZIP + EXT_GZIP);
			GZIPOutputStream gos = new GZIPOutputStream(new FileOutputStream(
					PATH + nameFile)); // Declaramos el OutputStream del GZIP
			// que crear� el archikvo con el
			// FileOutputStream
			ZipOutputStream zos = new ZipOutputStream(gos); // Declaramos el
			// ZipOutputStream
			// con la salida
			// redirigida al
			// GZIPOutputStream
			zos.putNextEntry(new ZipEntry(getNameFileByUrl(url, "")));

			// buffer para ir leyendo.
			byte[] array = new byte[1];

			// Primera lectura y bucle hasta el final
			int leido = is.read(array);
			while (leido > 0) {
				zos.write(array, 0, leido);
				leido = is.read(array);
			}
			// Cierre de conexion y fichero.
			is.close();
			zos.finish();
			zos.close();
			gos.finish();
			gos.close();
			System.out.println("Archivo Guardado en: " + PATH);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Funci�n para guardar el contenido de una URL Para ello se redirecciona la
	 * salida al FileOutputStream.
	 * 
	 * Esta funci�n utiliza la clase {@link HtmlToAscii} para quitar las
	 * etiquetas de la URL que descargamos.
	 * 
	 * @param is
	 *            InputStream a guardar
	 * @param url
	 *            Url que guardaremos
	 * @throws IOException
	 *             Excepci�n de Entrada y salida.
	 */
	public void saveUrlContentWithoutTags(InputStream is, URL url)
			throws IOException {
		try {
			FileOutputStream fos = new FileOutputStream(PATH
					+ getNameFileByUrl(url, EXT_ASC));
			System.out.println("Archivo Guardado en: " + PATH);
			HtmlToAscii html = new HtmlToAscii(is);

			// buffer para ir leyendo.
			byte[] array = new byte[1];

			// Primera lectura y bucle hasta el final
			int leido = html.read(array);
			while (leido > 0) {
				fos.write(array, 0, leido);
				leido = html.read(array);
			}

			is.close();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Funci�n para guardar el contenido de una URL en un .ZIP. Para ello se
	 * redirecciona la salida del OutputStream del ZIP al FileOutputStream.
	 * 
	 * Esta funci�n utiliza la clase {@link HtmlToAscii} para quitar las
	 * etiquetas de la URL que descargamos.
	 * 
	 * @param is
	 *            InputStream a guardar
	 * @param url
	 *            Url que guardaremos
	 * @throws IOException
	 *             Excepci�n de Entrada y salida.
	 */
	public void saveUrlContentWithoutTagsOnZip(InputStream is, URL url)
			throws IOException {
		try {
			ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(PATH
					+ getNameFileByUrl(url, EXT_ZIP)));
			zos.putNextEntry(new ZipEntry(getNameFileByUrl(url, EXT_ASC)));
			System.out.println("Archivo Guardado en: " + PATH);
			HtmlToAscii html = new HtmlToAscii(is);

			// buffer para ir leyendo.
			byte[] array = new byte[1];

			// Primera lectura y bucle hasta el final
			int leido = html.read(array);
			while (leido > 0) {
				zos.write(array, 0, leido);
				leido = html.read(array);
			}

			is.close();
			zos.finish();
			zos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Funci�n para guardar el contenido de una URL en un .GZ. Para ello se
	 * redirecciona la salida del OutputStream del GZIP al FileOutputStream.
	 * 
	 * Esta funci�n utiliza la clase {@link HtmlToAscii} para quitar las
	 * etiquetas de la URL que descargamos.
	 * 
	 * @param is
	 *            InputStream a guardar
	 * @param url
	 *            Url que guardaremos
	 * @throws IOException
	 *             Excepci�n de Entrada y salida.
	 */
	public void saveUrlContentWithoutTagsOnGZip(InputStream is, URL url)
			throws IOException {
		try {
			GZIPOutputStream gos = new GZIPOutputStream(new FileOutputStream(
					PATH + getNameFileByUrl(url, EXT_ASC + EXT_GZIP)));
			System.out.println("Archivo Guardado en: " + PATH);
			HtmlToAscii html = new HtmlToAscii(is);

			// buffer para ir leyendo.
			byte[] array = new byte[1];

			// Primera lectura y bucle hasta el final
			int leido = html.read(array);
			while (leido > 0) {
				gos.write(array, 0, leido);
				leido = html.read(array);
			}
			gos.finish();
			gos.close();
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Funci�n para guardar el contenido de una URL en un ZIP.GZ. Para ello se
	 * redirecciona la salida del OutputStream del ZIP al OutputStream del GZIP
	 * y este al FileOutputStream.
	 * 
	 * Esta funci�n utiliza la clase {@link HtmlToAscii} para quitar las
	 * etiquetas de la URL que descargamos.
	 * 
	 * @param is
	 *            InputStream a guardar
	 * @param url
	 *            Url que guardaremos
	 * @throws IOException
	 *             Excepci�n de Entrada y salida.
	 */
	public void saveUrlContentWithoutTagsOnZipAndGZip(InputStream is, URL url)
			throws IOException {
		try {

			String nameFile = getNameFileByUrl(url, EXT_ASC + EXT_ZIP
					+ EXT_GZIP);
			GZIPOutputStream gos = new GZIPOutputStream(new FileOutputStream(
					PATH + nameFile)); // Declaramos el OutputStream del GZIP
			// que crear� el archikvo con el
			// FileOutputStream
			ZipOutputStream zos = new ZipOutputStream(gos); // Declaramos el
			// ZipOutputStream
			// con la salida
			// redirigida al
			// GZIPOutputStream
			zos.putNextEntry(new ZipEntry(getNameFileByUrl(url, EXT_ASC)));

			HtmlToAscii html = new HtmlToAscii(is);
			// buffer para ir leyendo.
			byte[] array = new byte[1];

			// Primera lectura y bucle hasta el final
			int leido = html.read(array);
			while (leido > 0) {
				zos.write(array, 0, leido);
				leido = html.read(array);
			}
			// Cierre de conexion y fichero.
			is.close();
			zos.finish();
			zos.close();
			gos.finish();
			gos.close();
			System.out.println("Archivo Guardado en: " + PATH);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/**
	 * Obtiene el nombre del archivo a partir de la URL. Si la URL no especifica
	 * como debe de llamarse el archivo se le pondr� el nombre de Index.html. Si
	 * tambi�n existiera Index.html se pondr� el nombre Index2.html, Index3.html
	 * y as� sucesivamente.
	 * 
	 * @param URL
	 *            con la informaci�n de la url a descargar
	 * @return String con el nom
	 */
	public String getNameFileByUrl(URL url) {
		String strToReturn = url.getFile();
		int i = 0;
		if (strToReturn.isEmpty() || strToReturn.equals("/")) {
			if (arrayFiles == null)
				arrayFiles = new ArrayList<String>();
			i = 2;
			strToReturn = "index.html";
			File archivo = new File(PATH + strToReturn);
			arrayFiles.add(strToReturn);
			// Si existe index.html entra en el bucle
			while (archivo.exists() || !arrayFiles.contains(strToReturn)) {
				strToReturn = "index" + i + ".html";
				archivo = new File(PATH + strToReturn);
				i++;
				arrayFiles.add(strToReturn);
			}
		} else {
			strToReturn = strToReturn.substring(1);
			i = strToReturn.indexOf("/");
			strToReturn = strToReturn.substring(i + 1, strToReturn.length());
			File archivo = new File(PATH + strToReturn);
			if (strToReturn.equals("index.html")) {
				i = 2;
				if (arrayFiles == null)
					arrayFiles = new ArrayList<String>();
				// Si existe index.html entra en el bucle
				while (archivo.exists() || !arrayFiles.contains(strToReturn)) {
					strToReturn = "index" + i + ".html";
					archivo = new File(PATH + strToReturn);
					i++;
					arrayFiles.add(strToReturn);
				}
			}
		}

		// Comenzamos con i = 7 por el http://
		return strToReturn;
	}

	/**
	 * Obtiene el nombre del archivo a partir de la URL. Si la URL no especifica
	 * como debe de llamarse el archivo se le pondr� el nombre de Index.html. Si
	 * tambi�n existiera Index.html se pondr� el nombre Index2.html, Index3.html
	 * y as� sucesivamente. Esta funci�n utiliza el polimorfismo de
	 * getNameFileByUrl para poder analizar tambi�n los archivos de cualquier
	 * extensi�n
	 * 
	 * @param URL
	 *            con la informaci�n de la url a descargar
	 * @param extension
	 *            Extensi�n del archivo final
	 * @return String con el nom
	 */
	public String getNameFileByUrl(URL url, String extension) {
		String strToReturn = url.getFile();

		int i = 0;
		if (strToReturn.isEmpty() || strToReturn.equals("/")) {
			if (arrayFiles == null)
				arrayFiles = new ArrayList<String>();
			i = 2;
			strToReturn = "index.html" + extension;
			File archivo = new File(PATH + strToReturn);
			arrayFiles.add(strToReturn);
			// Si existe index.html entra en el bucle
			while (archivo.exists() || !arrayFiles.contains(strToReturn)) {
				// while (!arrayFiles.contains(strToReturn)) {
				strToReturn = "index" + i + ".html" + extension;
				archivo = new File(PATH + strToReturn);
				i++;
				arrayFiles.add(strToReturn);
			}
		} else {
			strToReturn = strToReturn.substring(1);
			i = strToReturn.indexOf("/");
			strToReturn = strToReturn.substring(i + 1, strToReturn.length());
			File archivo = new File(PATH + strToReturn + extension);
			if (strToReturn.equals("index.html")) {
				i = 2;
				if (arrayFiles == null)
					arrayFiles = new ArrayList<String>();
				// Si existe index.html entra en el bucle
				while (archivo.exists()
						|| !arrayFiles.contains(strToReturn + extension)) {
					strToReturn = "index" + i + ".html" + extension;
					archivo = new File(PATH + strToReturn + extension);
					arrayFiles.add(strToReturn + extension);
					i++;
				}
			} else
				strToReturn += extension;
		}

		// Comenzamos con i = 7 por el http://
		return strToReturn;
	}
}
